import Flutter
import UIKit
import TuyaSmartBaseKit
import TuyaSmartDeviceKit
import CoreLocation
import TuyaSmartActivatorKit
import TuyaSmartBLEKit

public class SwiftTySmartHomePlugin: NSObject, FlutterPlugin, TuyaSmartActivatorDelegate, TuyaSmartDeviceDelegate {

    var homeManager = TuyaSmartHomeManager()
    var home: TuyaSmartHome?
    var deviceID = ""
    var smartDevice: TuyaSmartDevice?
    var smartRequest = TuyaSmartRequest()
    var dataArr = [Any]()
    
    // 全局使用
    var homeIdGlobal: Int64 = 0
    var ssidGlobal = ""
    var passwordGlobal = ""

  public static func register(with registrar: FlutterPluginRegistrar) {
    let methodChannel = FlutterMethodChannel(name: "ty_smart_home", binaryMessenger: registrar.messenger())
    let instance = SwiftTySmartHomePlugin()
    registrar.addMethodCallDelegate(instance, channel: methodChannel)

     /**
         1. 在项目根目录添加安全图片 t_s.bmp
         2. 涂鸦平台注册 appKey 和 secretKey
     */
    let appKey = "xdcxpe7vsnhhmarwymev"
    let secretKey = "tyd59n9fgxckf5u4cgu87fthummeq4uw"
    TuyaSmartSDK.sharedInstance().start(withAppKey: appKey, secretKey:secretKey)
   
    
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    
    switch call.method {
        case "getPlatformVersion":
            result("iOS " + UIDevice.current.systemVersion)
        case "loginWithWIFI":
            loginApp(call: call, result: result)
        case "registerWithWIFI":
            registerApp(call: call, result: result)
        case "vertificateWithWIFI":
            getVertificateCode(call: call, result: result)
        case "resetPwdWithWIFI":
            resetPwdByPhone(call: call, result: result)
        /// 以 UID 形式登录
        case "loginWithUID":
            loginWithUID(call: call, result: result)
        ///  以 UID 形式注册
        case "registerWithUID":
            registerAppWithUID(call: call, result: result)
        /// 以 UID 形式登录, 若未注册过则进行注册
        case "loginOrRegisterWithUid":
            loginOrRegisterWithUid(call: call, result: result)
        /// 获取设备列表
        case "getDeviceList":
            getHomeList(call: call, result: result)
        case "modifyDeviceName":
            modifyDeviceName(call: call, result: result)
        case "removeDeviceInfo":
            removeDeviceInfo(call: call, result: result)
        case "getWIFIName":
            getWIFIName(call: call, result: result)
        case "getHomeID":
            getHomeID(call: call, result: result)
        case "commitEZModeAction":
            commitEZModeAction(call: call, result: result)
        case "startLocation":
            startLocation(call: call, result: result)
        case "configWithDeviceID":
            configWithDeviceID(call: call, result: result)
        case "go2WIFISetting":
            go2WIFISetting()
        case "loadHistoryData":
            loadHistoryData(call: call, result: result)
        /// 修改设备DP的值
        case "updateDeviceDPS":
            updateDeviceDPS(call: call, result: result)
        /// 向其他用户发送共享设备的邀请
        case "inviteShare":
            inviteShare(call: call, result: result)
        /// 确认分享邀请
        case "confirmShareInviteShare":
            confirmShareInviteShare(call: call, result: result)
        /// 移除主动共享的设备
        case "disableDevShare":
            disableDevShare(call: call, result: result)
        default:
            break
    }

  }
   
    // 登录
    func loginApp(call: FlutterMethodCall,
                result: @escaping FlutterResult) {
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let number = args["phoneNumber"] ?? ""
        let password = args["password"] ?? ""
        TuyaSmartUser.sharedInstance().login(byPhone: code, phoneNumber: number, password: password, success: {
            result(["result": "1"])
        }) { error in
            let error = error?.localizedDescription ?? ""
            result(["result": error])
            print("登录失败: \(error)")
        }
    }
    
    // 手机号注册
    func registerApp(call: FlutterMethodCall,
                     result: @escaping FlutterResult) {
        
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let number = args["phoneNumber"] ?? ""
        let password = args["password"] ?? ""
        let vertificate = args["vertificate"] ?? ""
        TuyaSmartUser.sharedInstance().register(byPhone: code, phoneNumber: number, password: password, code: vertificate, success: {
            result(["result": "1"])  // 注册成功
        }) { error in
            let error = error?.localizedDescription ?? ""
            result(["result": error])
            print("注册失败: \(error)")
        }
    }
    
    // 发送手机验证码: 必须真机测试
    func getVertificateCode(call: FlutterMethodCall,
                          result: @escaping FlutterResult) {
       let args = call.arguments as! [String: Any]
       let code = args["code"] as! String
       let number = args["phoneNumber"] as! String
       let type = args["type"] as! Int
        /**
         0: 用于登录,
         1: 用于手机号注册,
         2: 用于重置密码
         */
        TuyaSmartUser.sharedInstance().sendVerifyCode(code, phoneNumber: number, type: type, success: {
            result(["result": "1"]) // 获取验证码成功
        }) { error in
            print("获取验证码失败")
        }
    }
    
    // 手机密码重置
    func resetPwdByPhone(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let number = args["phoneNumber"] ?? ""
        let password = args["password"] ?? ""
        let vertificate = args["vertificate"] ?? ""
        
        TuyaSmartUser.sharedInstance().resetPassword(byPhone: code, phoneNumber: number, newPassword: password, code: vertificate, success: {
          result(["result": "1"]) // 重置密码成功
        }, failure: { error in
            print("获取验证码失败")
        })
    }
    
    // 以 UID 形式登录
    func loginWithUID(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let uid = args["uid"] ?? ""
        let password = args["password"] ?? ""
        
        TuyaSmartUser.sharedInstance().login(byUid: uid, password: password, countryCode: code, success: {
            print("登录涂鸦成功")
            result(["result": "1"])
          }, failure: { error in
            print("登录涂鸦失败")
            result(["result": "error"])
          })
    }
    
    // 以 UID 形式注册
    func registerAppWithUID(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let uid = args["uid"] ?? ""
        let password = args["password"] ?? ""
        
        TuyaSmartUser.sharedInstance().register(byUid: uid, password: password, countryCode: code, success: {
            result(["result": "1"]) // 重置密码成功
          }, failure: { error in
            result(["result": "error"])
          })
    }
    
    // 以 UID 形式登录, 若未注册过则进行注册
    func loginOrRegisterWithUid(call: FlutterMethodCall,
                                result: @escaping FlutterResult) {
        
        let args = call.arguments as! [String: String]
        let code = args["code"] ?? ""
        let uid = args["uid"] ?? ""
        let password = args["password"] ?? ""
        
        TuyaSmartUser.sharedInstance().loginOrRegister(withCountryCode: code, uid: uid, password: password, createHome: false, success: { (successId) in
            print("登录涂鸦成功-loginOrRegisterWithUid")
            result(["result": "1", "username": "username", "uid": uid])
        }, failure: { (error) in
            result(["result": "error"])
            if let e = error {
                print("loginOrRegisterWithCountryCode failure: \(e)")
            }
        })
    }
    
    func getHomeList(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
  //        homeManager.delegate = self

          // 获得详细家庭数据
          homeManager.getHomeList(success: { (homeModelArray) in
              if let dataArr = homeModelArray {
                  if dataArr.count > 0 { // 如果家庭已经存在, 选择第一个

                      if let model = homeModelArray?.first {

                          self.home = TuyaSmartHome(homeId: model.homeId)

                          // 获得详细家庭数据
                          self.home?.getDetailWithSuccess({ model in

                              print("家庭数据设备列表: deviceList\(self.home?.deviceList)")

                              var dataArr = [[String: Any]]()
                              self.home?.deviceList.forEach({ model in
                                
                                if model.devId.contains("vdevo") {  //排除演示设备
                                    return
                                }
                                  var dic = [String: Any]()
                                  dic["devId"] = model.devId
                                  dic["name"] = model.name
                                  dic["isOnline"] = model.isOnline
                                  dic["dps"] = model.dps
                                  dic["homeId"] = "\(model.homeId)"
                                  dic["dpCodes"] = model.dpName
                                  dataArr.append(dic)
                                
                                print("HomeID: \(model.homeId)")
                              })
                              result(dataArr)

                          }, failure: { error in
                              print("获取家庭详细信息失败: \(error?.localizedDescription)")
                          })
                      }

                  } else { // 添加一个默认的home
                      self.homeManager.addHome(
                          withName: "hangzhou's home",
                          geoName: "hangzhou",
                          rooms: ["bedroom"],
                          latitude: 0, longitude: 0, success: { (homeID) in
                              print("homeID: \(homeID)")
                            self.home = TuyaSmartHome(homeId: homeID)
                              
                            var dataArr = [[String: Any]]()
                            let dic = ["homeID": "\(homeID)","devID": ""]
                            dataArr.append(dic)
                            result(dataArr)
                            
                      }) { (error) in
                          print("添加家庭: \(error)")
                      }
                  }
              }
          }) { error in
            print("获取家庭设备\(error)")
          }
    }
    
    func getHomeID(call: FlutterMethodCall,
                   result: @escaping FlutterResult) {
        // 获得详细家庭数据
                  homeManager.getHomeList(success: { (homeModelArray) in
                      if let dataArr = homeModelArray {
                          if dataArr.count > 0 { // 如果家庭已经存在, 选择第一个

                              if let model = homeModelArray?.first {
                                
                                result("\(model.homeId)")
                              }

                          } else { // 添加一个默认的home
                              self.homeManager.addHome(
                                  withName: "hangzhou's home",
                                  geoName: "hangzhou",
                                  rooms: ["bedroom"],
                                  latitude: 0, longitude: 0, success: { (homeID) in
                                      print("homeID: \(homeID)")
                                      self.home = TuyaSmartHome(homeId: homeID)
                                    result("\(homeID)")
                                    
                              }) { (error) in
                                  print("添加家庭: \(error)")
                              }
                          }
                      }
                  }) { error in
                      print("获取家庭设备\(error)")
                  }
    }
    
    // 开始配网
    func commitEZModeAction(call: FlutterMethodCall,
                            result: @escaping FlutterResult) {
       let args = call.arguments as! [String: Any]
        let homeID: Int64 = Int64(args["homeID"] as! String)!
        
        let ssid = args["ssid"] as! String
        let pwd = args["password"] as! String
        TuyaSmartActivator.sharedInstance().getTokenWithHomeId(homeID, success: { [self] token in
            
            print("获取到Token: \(token)")
            // 暂时舍弃这种配网方式, 用双模配网
//            let sharedInstance = TuyaSmartActivator.sharedInstance()!
//            sharedInstance.delegate = self;
//            sharedInstance.startConfigWiFi(TYActivatorModeEZ,
//                                           ssid: ssid,
//                                           password: pwd,
//                                           token: token,
//                                           timeout: 100)
            
            // 设置代理
            TuyaSmartBLEManager.sharedInstance().delegate = self
            TuyaSmartBLEManager.sharedInstance().startListening(true)
            self.homeIdGlobal = homeID
            self.ssidGlobal = ssid
            self.passwordGlobal = pwd
            
        
        }, failure: { error in

            print("token fetch failed, error message is \(error)")
        })
    }

    // 修改名称
    func modifyDeviceName(call: FlutterMethodCall,
                        result: @escaping FlutterResult) {
        
        let args = call.arguments as! [String: String]
        let devId = args["devId"] ?? ""
        let name = args["name"] ?? ""
        let device = TuyaSmartDevice(deviceId: devId)
        device!.updateName(name, success: {  // 修改成功
            result(["result": "1"])
        }, failure: { error in
            let error = error?.localizedDescription ?? ""
            result(["result": error])
            print("修改设备名称失败: \(error)");
        })
    }
    
    // 移除设备
    func removeDeviceInfo(call: FlutterMethodCall,
                        result: @escaping FlutterResult) {
        let args = call.arguments as! [String: String]
        let devId = args["devId"] ?? ""
        let device = TuyaSmartDevice(deviceId: devId)
        device!.remove({  // 删除成功
            result(["result": "1"])
        }, failure: { error in
            let error = error?.localizedDescription ?? ""
            result(["result": error])
            print("删除设备失败: \(error)");
        })
    }
    
    // 获取WIFI名称(SSID)
    func getWIFIName(call: FlutterMethodCall,
                     result: @escaping FlutterResult) {
        
        let status = CLLocationManager.authorizationStatus()
        // 获取已连接的WIFI名称
        if let ssid = TuyaSmartActivator.currentWifiSSID() {
            result(["result": ssid])
            print("ssid: \(ssid)")
        } else {
            result(["result": "error"])
            
            if #available(iOS 13.0, *) {
                if status == .denied || status == .notDetermined || status == .restricted {
                                let wifiAlert = UIAlertController(title: "请开启“位置”权限以自动获取Wi-Fi名称", message: "", preferredStyle: .alert)
            
                                let action = UIAlertAction(title: "立即设置", style: .default, handler: { action in
            
                                })
                                wifiAlert.addAction(action)
//                                    self.present(wifiAlert, animated: true)
                }
            }
        }

    }

    // pragma mark - TuyaSmartActivatorDelegate
    public func activator(_ activator: TuyaSmartActivator!, didReceiveDevice deviceModel: TuyaSmartDeviceModel!, error: Error!) {
        if deviceModel != nil && error == nil {
            //配网成功
            print("配网成功")
            
            NotificationCenter.default.post(name: NSNotification.Name("getConfigWIFIResult"), object: nil, userInfo: ["result":"1"])
        }

        if let e = error {
            //配网失败
            print("配网失败\(e)")
            NotificationCenter.default.post(name: NSNotification.Name("getConfigWIFIResult"), object: nil, userInfo: ["result":"0"])
        }
    }
    
    // 开启定位权限
    func startLocation(call: FlutterMethodCall,
                  result: @escaping FlutterResult) {
        // 获取定位权限
        let state = CLLocationManager.authorizationStatus()
        let enabled = CLLocationManager.locationServicesEnabled()
        
        print("enable: \(enabled), state: \(state.rawValue)")
        if !enabled || state.rawValue < 2 {  // 尚未获取定位权限
            
            // 系统位置权限授权弹窗
            let locationManager = CLLocationManager()
            locationManager.requestAlwaysAuthorization()
            locationManager.requestWhenInUseAuthorization()
            result(["result": "1"])
        }
        
    }
    
    // 进入WIFI设备 (iOS只能跳到应用内设置界面)
    func go2WIFISetting() {
        if let url = URL(string: UIApplication.openSettingsURLString) {
                if #available(iOS 10.0, *) {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                } else {
                    UIApplication.shared.openURL(url)
                }
            }
    }
    
    // 获取历史数据
    // 获取功能点历史上报⽇志
    func loadHistoryData(call: FlutterMethodCall,
                         result: @escaping FlutterResult){
        let args = call.arguments as! [String: Any]
        let devId = args["devId"] ?? ""  // 设备 ID
        let dpIds = "102,110" // 要查询的 dp 点
        let offset = args["offset"] ?? 0 // 分页偏移量
        let limit = 1000  // 分页大小，一页的数据条数
        let startTime = args["startTime"] ?? "" // 开始时间戳
        let endTime = args["endTime"] ?? "" // 结束时间戳
        let sortType = "DESC"  // 顺序, 时间从大到小
        
        let param = ["devId": devId, "dpIds": dpIds,
                     "offset": offset, "limit": limit,
                     "startTime": startTime,
                     "endTime": endTime,
                     "sortType": sortType,] as [String : Any]
        
        smartRequest.request(withApiName: "tuya.m.smart.operate.all.log", postData: param, version: "1.0") { data in
            
            let d = data as! [String: Any]
            let dps = d["dps"] as! [[String:Any]]
            let hasNext = d["hasNext"] as! Bool
            let total = d["total"] as! Int
            
            self.dataArr.append(contentsOf: dps)
            
            result(["dataArr": dps, "hasNext": hasNext])
            print("获取历史数据成功: \(dps.count), hasNext: \(hasNext), total: \(total), 当前数量: \(self.dataArr.count)")
        } failure: { error in
            let error = error?.localizedDescription ?? ""
            print("获取历史数据失败: \(error)");
        }

    }
    
    /**
       设备信息
     */
    func configWithDeviceID(call: FlutterMethodCall,
                            result: @escaping FlutterResult)  {
        let args = call.arguments as! [String: Any]
        let deviceId = args["deviceId"] as! String
        if let device = TuyaSmartDevice(deviceId: deviceId) {
            device.delegate = self
            
            if #available(iOS 10.0, *) {
                Timer.scheduledTimer(withTimeInterval: 100, repeats: true) { (timer) in
                    NSLog("设备类型: %@", device.deviceModel.name)
                }
            } else {
                // Fallback on earlier versions
            }
        }
        
    }
    
    // Delegate
    public func device(_ device: TuyaSmartDevice, dpsUpdate dps: [AnyHashable : Any]) {
        // 设备的 dps 状态发生变化，刷新界面 UI
        
        let dps = device.deviceModel.dps!
        var temp = 0
        var humi = 0
        for element in device.deviceModel.schemaArray {
            let dpsId = element.dpId!
            switch dpsId {
            case "102":  // 温度
                temp = dps[dpsId] as! Int
            case "110":  // 湿度
                humi = dps[dpsId] as! Int
            default:
                break
            }
            // 传递温湿度数据
            NotificationCenter.default.post(name: NSNotification.Name("getTempHumi"), object: nil, userInfo: ["temp":"\(temp)", "humi": "\(humi)", "devId": "\(device.deviceModel.devId!)"])
        }
        print("设备数据变化\(dps)")
    }
    
    
    /*
        修改 DPS 数据
     */
    func updateDeviceDPS(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: Any]
        let devId = args["devId"] as! String
        let dpKey = args["dpKey"] as! String
        let dpValue = args["dpValue"]
        
        var dpId = ""
        
        guard let device = TuyaSmartDevice(deviceId: devId) else { return }
        
        // 选择数据点
        device.deviceModel.schemaArray.forEach { schemaModel in
            if schemaModel.code == dpKey {
                dpId = schemaModel.dpId
            }
        }
        
        // 发布更新
        device.publishDps([dpId: dpValue]) {
            result(["result": "1"])
            print("修改设备参数成功: \(dpKey)")
        } failure: { error in
            let errorMessage = error?.localizedDescription ?? ""
            print("修改设备参数失败: \(errorMessage)")
            result(["result": errorMessage])
        }

    }
    
    
    /**
        向其他用户发送共享设备的邀请
     */
    func inviteShare(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: Any]
        let devId = args["devId"] as! String  // 设备ID
        let code = args["code"] as! String // 国家码
        let uid = args["uid"] as! String   // 用户ID
        
        TuyaSmartHomeDeviceShare().invite(withCountryCode: code, userAccount: uid, devId: devId) { (data) in
            result(["result": "\(data)"])
            print("发送共享设备的邀请: 成功")
        } failure: { (error) in
            let errorMessage = error?.localizedDescription ?? ""
            print("发送共享设备的邀请: \(errorMessage)")
            result(["result": "0"])
        }
    }
    
    /**
        确认分享邀请
     */
    func confirmShareInviteShare(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        
        let args = call.arguments as! [String: Any]
        let shareId = args["shareId"] as! Int  // 设备ID
        TuyaSmartHomeDeviceShare().confirmInviteShare(withShareId: shareId) {
            print("确认共享设备的邀请: 成功")
            result(["result": "1"])
        } failure: { (error) in
            let errorMessage = error?.localizedDescription ?? ""
            print("确认共享设备的邀请: \(errorMessage)")
            result(["result": "0"])
        }
    }
    
    /**
        移除主动共享的设备
     */
    func disableDevShare(call: FlutterMethodCall,
                       result: @escaping FlutterResult) {
        let args = call.arguments as! [String: Any]
        let devId = args["devId"] as! String

        TuyaSmartHomeDeviceShare().removeReceive(withDevId: devId, success: {
            print("移除共享设备: 成功")
            result(["result": "1"])
        }, failure: { (error) in
            let errorMessage = error?.localizedDescription ?? ""
            print("移除共享设备: \(errorMessage)")
            result(["result": "0"])
        })
    }
    

}


//MARK: -Delegate
extension SwiftTySmartHomePlugin: TuyaSmartBLEManagerDelegate  {
    
    /**
     * 蓝牙状态变化通知
     *
     * @param isPoweredOn 蓝牙状态，开启或关闭
     */
    public func bluetoothDidUpdateState(_ isPoweredOn: Bool) {

    }
    /**
     * 扫描到未激活的设备
     *
     * @param uuid 未激活设备 UUID
     * @param productKey 未激活设备产品 key
     */
    public func didDiscoveryDevice(withDeviceInfo deviceInfo: TYBLEAdvModel) {
        print("didDiscoveryDevice: 已经发现设备")
        
        // 成功扫描到未激活的设备
        // 若设备已激活，则不会走此回调，且会自动进行激活连接
        let type = deviceInfo.bleType
        
        guard
            type == TYSmartBLETypeBLEWifiSecurity ||
            type == TYSmartBLETypeBLEWifi ||
            type == TYSmartBLETypeBLELTESecurity
        else {
            return
        }
        
        TuyaSmartBLEWifiActivator.sharedInstance().bleWifiDelegate = self
        
        print(
              "ssid: \(ssidGlobal), password : \(passwordGlobal),homeId: \(homeIdGlobal)")
        TuyaSmartBLEWifiActivator.sharedInstance() .startConfigBLEWifiDevice(withUUID: deviceInfo.uuid, homeId: homeIdGlobal, productId: deviceInfo.productId, ssid: ssidGlobal, password: passwordGlobal, timeout: 120, success: {
                // 下发成功
            print("开启配网成功")
            
            }) {
                // 下发失败
                print("开启配网失败")
                
            }
    }
    
}

extension SwiftTySmartHomePlugin: TuyaSmartBLEWifiActivatorDelegate {
    /// 配网的结果回调
    public func bleWifiActivator(_ activator: TuyaSmartBLEWifiActivator, didReceiveBLEWifiConfigDevice deviceModel: TuyaSmartDeviceModel?, error: Error?) {
        print("配网结果: \(String(describing: error))")
        
        if (error == nil && deviceModel != nil) {
                // 配网成功
            print("配网成功")
            
            NotificationCenter.default.post(name: NSNotification.Name("getConfigWIFIResult"), object: nil, userInfo: ["result":"1"])
            //在配网结束后调用
            TuyaSmartBLEManager.sharedInstance().delegate = nil
            TuyaSmartBLEManager.sharedInstance().stopListening(true)
            
            TuyaSmartBLEWifiActivator.sharedInstance().bleWifiDelegate = nil
            TuyaSmartBLEWifiActivator.sharedInstance().stopDiscover()
        }

        if (error != nil) {
            // 配网失败
            print("配网失败\(String(describing: error))")
            NotificationCenter.default.post(name: NSNotification.Name("getConfigWIFIResult"), object: nil, userInfo: ["result":"0"])
            
            //在配网结束后调用
            TuyaSmartBLEManager.sharedInstance().delegate = nil
            TuyaSmartBLEManager.sharedInstance().stopListening(true)
            
            TuyaSmartBLEWifiActivator.sharedInstance().bleWifiDelegate = nil
            TuyaSmartBLEWifiActivator.sharedInstance().stopDiscover()
        }
    }
}
